package com.fa4j.common.data.config;

import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.fa4j.common.base.model.ModuleInfo;
import com.fa4j.common.base.model.ModuleType;
import com.fa4j.common.data.model.CommonDataConst;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Slf4j
@AutoConfiguration
@AutoConfigureBefore(MybatisPlusAutoConfiguration.class)
@PropertySource(value = "classpath:mybatis-plus-default.properties")
public class CommonDataAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean({MapperScannerConfigurer.class})
    public MapperScannerConfigurer mapperScannerConfigurer(List<ModuleInfo> moduleInfoList) {
        String basePackage = moduleInfoList.stream()
                .filter(info -> info.getType() == ModuleType.BIZ)
                .map(info -> info.getPackageName() + ".repository.mapper")
                .collect(Collectors.joining(","));
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setProcessPropertyPlaceHolders(false);
        configurer.setAnnotationClass(Mapper.class);
        configurer.setBasePackage(basePackage);
        return configurer;
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        // 乐观锁
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

    @Bean
    public MetaObjectHandler baseMetaObjectHandler() {
        return new MetaObjectHandler() {
            @Override
            public void insertFill(MetaObject metaObject) {
                this.strictInsertFill(metaObject, CommonDataConst.MYBATIS_PLUS_FIELD_DELETED, Boolean.class, false);
                this.strictInsertFill(metaObject, CommonDataConst.MYBATIS_PLUS_FIELD_CREATE_TIME, LocalDateTime.class,
                        LocalDateTime.now());
                this.strictInsertFill(metaObject, CommonDataConst.MYBATIS_PLUS_FIELD_UPDATE_TIME, LocalDateTime.class,
                        LocalDateTime.now());
            }

            @Override
            public void updateFill(MetaObject metaObject) {
                this.strictUpdateFill(metaObject, CommonDataConst.MYBATIS_PLUS_FIELD_UPDATE_TIME, LocalDateTime.class,
                        LocalDateTime.now());
            }

            @Override
            public MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {
                Object obj = fieldVal.get();
                if (Objects.nonNull(obj)) {
                    metaObject.setValue(fieldName, obj);
                }
                return this;
            }
        };
    }


}
